<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

    <button onclick="handlePause()">终止</button>
    <button onclick="start()">开始</button>
    <script>
        // AbortController
        const buildCancelableTask = () => {
            let abortController = null

            return {
                run(asyncFn) {
                    // 每次都开启
                    abortController = new AbortController()
                    return new Promise((resolve, reject) => {
                        const cancelTask = () => reject(new Error('task canceled'))

                        // 如果开始就是终止，就取消任务
                        if (abortController.signal.aborted) {
                            cancelTask()
                            return
                        }


                        // 执行任务，注意这里的resolve和reject是promise的resolve和reject
                        asyncFn().then(resolve, reject)

                        // 监听取消事件，如果取消就终止任务
                        abortController.signal.addEventListener('abort', cancelTask)


                    })
                },

                cancel() {
                    abortController.abort()
                }
            }

        }


        const { run, cancel } = buildCancelableTask()

        const asyncFn = () => {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve('success')
                }, 3000)
            })
        }

        function start() {
            run(asyncFn).then((err) => {
                console.log('任务结果', err);
            }).catch((err) => {
                console.log('任务终止', err);
            })
        }

        function handlePause() {
            cancel()
        }
    </script>
</body>

</html>